/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Cards;

import java.util.Objects;

/**
 * Class UnoCard. It can use to manage UnoCard
 * @author masterinftel11
 */
public class UnoCard extends Card implements Comparable<UnoCard> {
    private final Number rank;
    private final Colour suit;
    
    /**
     * Manage symbolA to UnoCard. Number of Card. It can be ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TAKETWO, REVERSE, NEXT, COLOURCHANGE, TAKEFOUR.
     */
    public enum Number implements SymbolA{
        ZERO(0), ONE(1),TWO(2),THREE(3),FOUR(4),FIVE(5),SIX(6),SEVEN(7), EIGHT(8),NINE(9),
        TAKETWO(10), REVERSE(11), NEXT(12), COLOURCHANGE(13), TAKEFOUR(14);
        
        private final int code;
        
        public int getCode() {
            return code;
        }
        
        private Number(int code) {
            this.code = code;
        }
        
        public static Number valueOf(int code) {
            for (Number rank: Number.values()) {
                if (rank.getCode()==code)
                    return rank;
            }
            throw new RuntimeException("INVALID CODE");
        }
    }
    
    /**
     * Manage symbolB to UnoCard. It can be RED, BLUE, YELLOW, GREEN, NEUTRAL.
     */
    public enum Colour implements SymbolB{
        RED(1),BLUE(2),YELLOW(3),GREEN(4), NEUTRAL(5);
        
        private final int code;
        
        public int getCode() {
            return code;
        }
        
        private Colour(int code) {
            this.code = code;
        }
        
        public static Colour valueOf(int code) {
            for (Colour suit: Colour.values()) {
                if (suit.getCode()==code)
                    return suit;
            }
            throw new RuntimeException("INVALID CODE");
        }
    }
    
    /**
     * Method to initialize UnoCard through value of rank and suit
     * @param rank of card
     * @param suit or cark
     */
    public UnoCard(int rank,int suit) {
        this.suit = Colour.valueOf(suit);
        this.rank = Number.valueOf(rank);
    }
    
    /**
     * Method to initialize UnoCard through value of rank and suit
     * @param rank of card
     * @param suit or cark
     */
    public UnoCard(Number rank, Colour suit) {
        this.suit = suit;
        this.rank = rank;
    }
    
    /**
     * Method to get rank
     * @return rank
     */
    public Number getRank() {
        return rank;
    }
    
    /**
     * Method to set suit
     * @return suit
     */
    public Colour getSuit() {
        return suit;
    }
    
    /**
     * Method to get points
     * @return points
     */
    public int points(){
        int points;
        if (this.isSpecialCard()){
            points = 20;
        }
        else if (this.isJoker()){
            points = 50;
        }
        else{
            points = this.getRank().getCode();
        }
        return points;
    }
    
    /**
     * Method to give if card is Joker
     * @return true if it his
     *         false otherwise
     */
    public boolean isJoker(){
        return this.getRank().equals(Number.COLOURCHANGE) || this.getRank().equals(Number.TAKEFOUR);
    }
    
    /**
     * Method to give if card is special
     * @return true if it his
     *         false otherwise
     */
    public boolean isSpecialCard () {
        return this.getRank().equals(Number.TAKETWO) || this.getRank().equals(Number.REVERSE) || this.getRank().equals(Number.NEXT);
    }
    
    @Override
    public String toString() {
        return getRank().name() + " " + getSuit().name();
    }
    
    @Override
    public int compareTo(UnoCard o) {
        int mayor;
        if(this.getSuit().getCode() > o.getSuit().getCode()){
            mayor = 1;
        }
        else if(this.getSuit().getCode() < o.getSuit().getCode()){
            mayor = -1;
        }
        else{
            if(this.getRank().getCode() > o.getRank().getCode()){
                mayor = 1;
            }
            else
                mayor = -1;
        }
        return mayor;
    }

    @Override
    public int hashCode() {
        int hash = 5;
        hash = 83 * hash + Objects.hashCode(this.rank);
        hash = 83 * hash + Objects.hashCode(this.suit);
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final UnoCard other = (UnoCard) obj;
        if (this.rank != other.rank) {
            return false;
        }
        return this.suit == other.suit;
    }
}